package com.yiyuan.app.service.impl;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.alibaba.fastjson.JSON;
import com.yiyuan.app.entity.constant.MQTTPrizeBonusConstant;
import com.yiyuan.app.entity.constant.MQTTTopicConstant;
import com.yiyuan.app.entity.message.BackedMessage;
import com.yiyuan.app.entity.message.BarrageMessage;
import com.yiyuan.app.mqtt.MQTTProducer;
import com.yiyuan.app.service.BaseUtilService;
import com.yiyuan.app.service.MQTTService;
import com.yiyuan.app.dao.*;
import com.yiyuan.app.entity.enums.*;
import com.yiyuan.app.entity.po.*;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Service
@AllArgsConstructor
public class MQTTServiceImpl implements MQTTService {

    private final GRecordGameDAO gRecordGameDAO;
    private final GConfRoomDAO gConfRoomDAO;
    private final UAppUserEquityDAO uAppUserEquityDAO;
    private final UAppUserDAO uAppUserDAO;
    private final BaseUtilService baseUtilService;
    private final DDetailsPineconeDAO dDetailsPineconeDAO;
    private final MRecordTaskDailyDAO mRecordTaskDailyDAO;
    private final MRecordTaskDAO mRecordTaskDAO;
    private final DDetailsPineNutDAO dDetailsPineNutDAO;
    private final GConfPrizeDAO gConfPrizeDAO;
    private final GConfPrizeItemDAO gConfPrizeItemDAO;
    private final GConfRoomPrizeDAO gConfRoomPrizeDAO;
    private final GRecordPrizeDAO gRecordPrizeDAO;
    private final MRankPushCoinsDAO mRankPushCoinsDAO;
    private final MRecordOccupyDAO mRecordOccupyDAO;
    private final GConfDeviceDAO gConfDeviceDAO;
    private final GConfRoomDeviceDAO gConfRoomDeviceDAO;
    private final GRoomRepairRecordDAO gRoomRepairRecordDAO;
    private final MRecordProductLookDAO mRecordProductLookDAO;
    private final MRecordNoticeDAO mRecordNoticeDAO;
    private final GRecordMqttMessageDAO gRecordMqttMessageDAO;
    private final MConfVipDAO mConfVipDAO;
    private final MRecordBattleArcadeMachineDAO mRecordBattleArcadeMachineDAO;
    private final MRecordBattleRecreationDAO mRecordBattleRecreationDAO;
    private final MRankBattleArcadeMachineDAO mRankBattleArcadeMachineDAO;
    private final MRankBattleRecreationDAO mRankBattleRecreationDAO;
    private final MRecordBattlePushCoinsDAO mRecordBattlePushCoinsDAO;
    private final MRankArcadeMachineDAO mRankArcadeMachineDAO;
    private final MRankBattlePushCoinsDAO mRankBattlePushCoinsDAO;
    private final MQTTProducer messageProducer;

    @Override
    @Transactional
    public Boolean dealPushCoins(GRecordMqttMessagePO messagePO) throws MqttException {
        GRecordGamePO gamePO = gRecordGameDAO.findById(messagePO.getGameId());
        GConfRoomPO roomPO = gConfRoomDAO.findById(gamePO.getRoomId());
        Integer usePinecone = roomPO.getMultipleValue() * Integer.parseInt(messagePO.getMessage());
        gRecordGameDAO.updateData(gamePO.getId(), usePinecone, 0, messagePO.getCreateTime());
        if (Objects.isNull(gamePO.getRecordOccupyId())) {
            UAppUserEquityPO equityPO = uAppUserEquityDAO.findByUserIdLock(gamePO.getUserId());
            if (equityPO.getPinecone() < usePinecone) {
                return Boolean.TRUE;
            }
            uAppUserEquityDAO.addPinecone(gamePO.getUserId(), -usePinecone);
            DDetailsPineconePO myDetail = new DDetailsPineconePO();
            myDetail.setUserId(gamePO.getUserId());
            myDetail.setLabelType(LabelTypeEnum.play_pay.getCode());
            myDetail.setDetailsType(DetailsTypeEnum.pay_out.getCode());
            myDetail.setPinecone(usePinecone);
            dDetailsPineconeDAO.save(myDetail);
        } else {
            MRecordOccupyPO occupyPO = mRecordOccupyDAO.findByIdLock(gamePO.getRecordOccupyId());
            if (occupyPO.getCurrentPinecone() < usePinecone) {
                return Boolean.TRUE;
            }
            mRecordOccupyDAO.addPinecone(gamePO.getRecordOccupyId(), -usePinecone);
        }
        messageProducer.sendIoMessage(MQTTTopicConstant.DEAL_TASK, gamePO.getId().toString(), 1);
        if (roomPO.getRoomType().equals(RoomTypeEnum.push_coins.getCode()) && Objects.isNull(gamePO.getRecordOccupyId())) {
            gRecordGameDAO.updatePushCoinsEndTime(gamePO.getId());
        }
        messagePO.setStatus(Boolean.TRUE);
        gRecordMqttMessageDAO.updateById(messagePO);
        return Boolean.TRUE;
    }

    @Override
    @Transactional
    public Boolean dealPushCoinsResult(GRecordMqttMessagePO messagePO) {
        GRecordGamePO gamePO = gRecordGameDAO.findById(messagePO.getGameId());
        GConfRoomPO roomPO = gConfRoomDAO.findById(gamePO.getRoomId());
        Integer pinecone = Math.multiplyExact(roomPO.getMultipleValue(), Integer.parseInt(messagePO.getMessage()));
        Integer getPineNut = Math.multiplyExact(pinecone, 10);
        gRecordGameDAO.updateData(gamePO.getId(), 0, getPineNut, null);
        if (Objects.isNull(gamePO.getRecordOccupyId())) {
            uAppUserEquityDAO.updatePineNut(gamePO.getUserId(), getPineNut);
            DDetailsPineNutPO pineNutPO = new DDetailsPineNutPO();
            pineNutPO.setUserId(gamePO.getUserId());
            pineNutPO.setLabelType(PineNutLabelTypeEnum.game.getCode());
            pineNutPO.setDetailsType(DetailsTypeEnum.income.getCode());
            pineNutPO.setPineNut(getPineNut);
            pineNutPO.setRoomId(roomPO.getId());
            pineNutPO.setRoomName(roomPO.getRoomName());
            dDetailsPineNutDAO.save(pineNutPO);
        } else {
            UAppUserEquityPO equityPO = uAppUserEquityDAO.findOne(UAppUserEquityPO::getUserId, gamePO.getUserId());
            MConfVipPO vipPO = mConfVipDAO.findOne(MConfVipPO::getVipLevel, equityPO.getVipGrade());
            Integer getPinecone = new BigDecimal(getPineNut).divide(new BigDecimal(vipPO.getExchangeRate()), 1, BigDecimal.ROUND_UP).multiply(new BigDecimal(10)).intValue();
            mRecordOccupyDAO.addPinecone(gamePO.getRecordOccupyId(), getPinecone);
        }

        // 结算挑战
        GRecordGamePO gRecordGamePO = gRecordGameDAO.findById(messagePO.getGameId());
        MRecordBattlePushCoinsPO battlePushCoinsPO = mRecordBattlePushCoinsDAO.findBattlingByUserId(gamePO.getUserId());
        if (Objects.nonNull(battlePushCoinsPO)) {
            MRankBattlePushCoinsPO pushCoinsPO = mRankBattlePushCoinsDAO.findById(battlePushCoinsPO.getBattleId());
            battlePushCoinsPO.setPineNut(gRecordGamePO.getGetPineNut().intValue());
            if (gRecordGamePO.getGetPineNut() >= pushCoinsPO.getPineNut()) {
                battlePushCoinsPO.setGameId(gamePO.getId());
                battlePushCoinsPO.setStatus(BattleStatusEnum.unclaimed.getCode());
                mRecordBattlePushCoinsDAO.updateById(battlePushCoinsPO);
            }
        }
        if (roomPO.getRoomType().equals(RoomTypeEnum.push_coins.getCode()) && Objects.isNull(gamePO.getRecordOccupyId())) {
            gRecordGameDAO.updatePushCoinsEndTime(gamePO.getId());
        }
        messagePO.setStatus(Boolean.TRUE);
        gRecordMqttMessageDAO.updateById(messagePO);
        return Boolean.TRUE;
    }

    @Override
    @Transactional
    public Boolean dealPrizeResult(GRecordMqttMessagePO messagePO) throws IOException {
        LocalDate now = LocalDate.now();
        GRecordGamePO gamePO = gRecordGameDAO.findById(messagePO.getGameId());
        UAppUserPO userPO = uAppUserDAO.findById(gamePO.getUserId());
        UAppUserEquityPO equityPO = uAppUserEquityDAO.findOne(UAppUserEquityPO::getUserId, gamePO.getUserId());
        GConfRoomPO roomPO = gConfRoomDAO.findById(gamePO.getRoomId());
        String msg = messagePO.getMessage();
        msg = msg.replace("{", "");
        msg = msg.replace("}", "");
        String[] split1 = msg.split(";");
        String[] split2 = split1[0].split("=");
        Integer bonus = Integer.parseInt(split2[1]);
        Integer pushValue = null;
        Integer pinecone;
        Integer taskActionCode = null;
        String prizeName;
        MRecordNoticePO noticePO = new MRecordNoticePO();
        if (bonus.equals(MQTTPrizeBonusConstant.PUSH_COINS_JP1)) {
            GConfRoomPrizePO roomPrizePO = gConfRoomPrizeDAO.findOnePrize(roomPO.getId(), PrizeTypeEnum.JP.getCode());
            if (Objects.isNull(roomPrizePO)) {
                log.info("房间ID【" + roomPO.getId() + "】未配置JP奖励");
                return Boolean.TRUE;
            }
            GConfPrizePO prizePO = gConfPrizeDAO.findById(roomPrizePO.getPrizeId());
            GConfPrizeItemPO itemPO = gConfPrizeItemDAO.findOneByItemCode(prizePO.getId(), PushCoinsPrizeEnum.JP1.getCode());
            pushValue = new BigDecimal("0.1").multiply(new BigDecimal(roomPO.getMultipleValue())).intValue();
            pinecone = itemPO.getItemValue();
            taskActionCode = TaskActionEnum.total_JP1.getCode();
            prizeName = "JP1";
            noticePO.setNoticeType(NoticeTypeEnum.JP1.getCode());
        } else if (bonus.equals(MQTTPrizeBonusConstant.PUSH_COINS_JP2)) {
            GConfRoomPrizePO roomPrizePO = gConfRoomPrizeDAO.findOnePrize(roomPO.getId(), PrizeTypeEnum.JP.getCode());
            if (Objects.isNull(roomPrizePO)) {
                log.info("房间ID【" + roomPO.getId() + "】未配置JP奖励");
                return Boolean.TRUE;
            }
            GConfPrizePO prizePO = gConfPrizeDAO.findById(roomPrizePO.getPrizeId());
            GConfPrizeItemPO itemPO = gConfPrizeItemDAO.findOneByItemCode(prizePO.getId(), PushCoinsPrizeEnum.JP2.getCode());
            pushValue = new BigDecimal("0.2").multiply(new BigDecimal(roomPO.getMultipleValue())).intValue();
            pinecone = itemPO.getItemValue();
            taskActionCode = TaskActionEnum.total_JP2.getCode();
            prizeName = "JP2";
            noticePO.setNoticeType(NoticeTypeEnum.JP2.getCode());
        } else if (bonus.equals(MQTTPrizeBonusConstant.PUSH_COINS_JP3)) {
            GConfRoomPrizePO roomPrizePO = gConfRoomPrizeDAO.findOnePrize(roomPO.getId(), PrizeTypeEnum.JP.getCode());
            if (Objects.isNull(roomPrizePO)) {
                log.info("房间ID【" + roomPO.getId() + "】未配置JP奖励");
                return Boolean.TRUE;
            }
            GConfPrizePO prizePO = gConfPrizeDAO.findById(roomPrizePO.getPrizeId());
            GConfPrizeItemPO itemPO = gConfPrizeItemDAO.findOneByItemCode(prizePO.getId(), PushCoinsPrizeEnum.JP3.getCode());
            pushValue = new BigDecimal("0.3").multiply(new BigDecimal(roomPO.getMultipleValue())).intValue();
            pinecone = itemPO.getItemValue();
            taskActionCode = TaskActionEnum.total_JP3.getCode();
            prizeName = "JP3";
            noticePO.setNoticeType(NoticeTypeEnum.JP3.getCode());
        } else if (bonus.equals(MQTTPrizeBonusConstant.PUSH_COINS_JPALL)) {
            GConfRoomPrizePO roomPrizePO = gConfRoomPrizeDAO.findOnePrize(roomPO.getId(), PrizeTypeEnum.JP.getCode());
            if (Objects.isNull(roomPrizePO)) {
                log.info("房间ID【" + roomPO.getId() + "】未配置JP奖励");
                return Boolean.TRUE;
            }
            GConfPrizePO prizePO = gConfPrizeDAO.findById(roomPrizePO.getPrizeId());
            GConfPrizeItemPO itemPO = gConfPrizeItemDAO.findOneByItemCode(prizePO.getId(), PushCoinsPrizeEnum.JPALL.getCode());
            pushValue = new BigDecimal("0.5").multiply(new BigDecimal(roomPO.getMultipleValue())).intValue();
            pinecone = itemPO.getItemValue();
            taskActionCode = TaskActionEnum.total_ALL.getCode();
            prizeName = "全盘奖";
            noticePO.setNoticeType(NoticeTypeEnum.ALL.getCode());
        } else {
            String[] split3 = split1[2].split("=");
            Integer award = Integer.parseInt(split3[1]);
            GConfRoomPrizePO numberRoomPrizePO = gConfRoomPrizeDAO.findOnePrize(roomPO.getId(), PrizeTypeEnum.number.getCode());
            if (Objects.isNull(numberRoomPrizePO)) {
                log.info("房间ID【" + roomPO.getId() + "】未配置数字奖励");
                return Boolean.TRUE;
            }
            GConfPrizePO numberPrizePO = gConfPrizeDAO.findById(numberRoomPrizePO.getPrizeId());
            List<GConfPrizeItemPO> pos = gConfPrizeItemDAO.findList(GConfPrizeItemPO::getPrizeId, numberPrizePO.getId());
            Map<Integer, Integer> collect = pos.stream().collect(Collectors.toMap(GConfPrizeItemPO::getScore, GConfPrizeItemPO::getItemValue));
            if (Objects.nonNull(collect.get(award))) {
                pinecone = collect.get(award);
                prizeName = award + "奖";
                noticePO.setNoticeType(NoticeTypeEnum.NUMBER.getCode());
                noticePO.setScore(award);
            } else {
                return Boolean.TRUE;
            }
        }
        // 新增松果记录
        uAppUserEquityDAO.addPinecone(gamePO.getUserId(), pinecone);
        DDetailsPineconePO pineconePO = new DDetailsPineconePO();
        pineconePO.setUserId(gamePO.getUserId());
        pineconePO.setLabelType(LabelTypeEnum.reward.getCode());
        pineconePO.setDetailsType(DetailsTypeEnum.income.getCode());
        pineconePO.setPinecone(pinecone);
        pineconePO.setRemark("赏金奖励：" + prizeName);
        dDetailsPineconeDAO.save(pineconePO);

        // 每日任务累计赏金
        String dailyKey = gamePO.getUserId() + now.toString() + "dailyTask";
        String key = gamePO.getUserId() + now.toString() + "task";
        baseUtilService.setDailyTask(dailyKey, gamePO.getUserId(), now);
        baseUtilService.setTask(key, gamePO.getUserId());
        List<MRecordTaskDailyPO> list = mRecordTaskDailyDAO.findUserTodayAction(gamePO.getUserId(), now, DailyTaskActionEnum.total_prize.getCode());
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(po -> {
                po.setCurrentProgress(Math.addExact(po.getCurrentProgress(), 1));
                if (po.getCurrentProgress() >= po.getThreshold() && po.getStatus().equals(TaskStatusEnum.go_complete.getCode())) {
                    po.setStatus(TaskStatusEnum.unclaimed.getCode());
                }
            });
            mRecordTaskDailyDAO.updateBatchById(list);
        }
        baseUtilService.dealDailyTaskAllComplete(gamePO.getUserId(), now);
        // 长期任务累计赏金
        List<MRecordTaskPO> pos = mRecordTaskDAO.findList(gamePO.getUserId(), TaskActionEnum.total_prize.getCode(), Collections.singletonList(TaskStatusEnum.go_complete.getCode()));
        if (CollectionUtils.isNotEmpty(pos)) {
            pos.forEach(po -> {
                po.setCurrentProgress(Math.addExact(po.getCurrentProgress(), 1));
                if (po.getCurrentProgress() >= po.getThreshold()) {
                    po.setStatus(TaskStatusEnum.unclaimed.getCode());
                }
            });
            mRecordTaskDAO.updateBatchById(pos);
        }
        if (Objects.nonNull(taskActionCode)) {
            // 长期任务累计JP赏金
            List<MRecordTaskPO> jpPos = mRecordTaskDAO.findList(gamePO.getUserId(), taskActionCode, Collections.singletonList(TaskStatusEnum.go_complete.getCode()));
            if (CollectionUtils.isNotEmpty(jpPos)) {
                jpPos.forEach(po -> {
                    po.setCurrentProgress(Math.addExact(po.getCurrentProgress(), 1));
                    if (po.getCurrentProgress() >= po.getThreshold()) {
                        po.setStatus(TaskStatusEnum.unclaimed.getCode());
                    }
                });
                mRecordTaskDAO.updateBatchById(jpPos);
            }
        }
        // 新增赏金审批记录
        GRecordPrizePO po = new GRecordPrizePO();
        po.setUserId(gamePO.getUserId());
        po.setRoomId(roomPO.getId());
        po.setRoomName(roomPO.getRoomName());
        po.setRoomType(roomPO.getRoomType());
        po.setPrizeType(prizeName);
        po.setPrizePinecone(pinecone);
        po.setStatus(PrizeStatusEnum.issued.getCode());
        gRecordPrizeDAO.save(po);

        if (Objects.nonNull(pushValue)) {
            LocalDate startOfWeek = now.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
            LocalDate endOfWeek = now.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
            String pushCoinsRankKey = gamePO.getUserId() + startOfWeek.toString() + endOfWeek.toString();
            Long rankId = baseUtilService.setPushCoinsRank(pushCoinsRankKey, gamePO.getUserId(), startOfWeek, endOfWeek);
            mRankPushCoinsDAO.addPushCoinsValue(rankId, pushValue);
        }

        if (roomPO.getRoomType().equals(RoomTypeEnum.push_coins.getCode()) && Objects.isNull(gamePO.getRecordOccupyId())) {
            gRecordGameDAO.updatePushCoinsEndTime(gamePO.getId());
        }

        // 新增公告
        noticePO.setPinecone(pinecone);
        noticePO.setUserId(gamePO.getUserId());
        noticePO.setRoomId(roomPO.getId());
        noticePO.setRoomName(roomPO.getRoomName());
        mRecordNoticeDAO.save(noticePO);

        // 推送弹幕
        BarrageMessage barrageMessage = new BarrageMessage();
        barrageMessage.setRoomId(roomPO.getId());
        barrageMessage.setNickName(userPO.getNickname());
        barrageMessage.setAvatarurl(userPO.getAvatarurl());
        barrageMessage.setVipLevel(equityPO.getVipGrade());
        barrageMessage.setContent("打出" + prizeName + "，奖励" + pinecone + "松果");
        messageProducer.sendMessage(MQTTTopicConstant.ROOM_BARRAGE_KEY, JSON.toJSONString(barrageMessage));

        messagePO.setStatus(Boolean.TRUE);
        gRecordMqttMessageDAO.updateById(messagePO);

        //推送管理后台
        BackedMessage backedMessage = new BackedMessage();
        backedMessage.setId(userPO.getId());
        backedMessage.setTitle(userPO.getNickname());
        backedMessage.setStatus("待审批");
        backedMessage.setDesc(prizeName);
        backedMessage.setMsgTime(LocalDateTimeUtil.format(LocalDateTime.now(), "yyyy-MM-dd HH:mm:ss"));
        messageProducer.sendMessage(MQTTTopicConstant.PRIZE_CHECK, JSON.toJSONString(backedMessage));
        return Boolean.TRUE;
    }

    @Override
    @Transactional
    public Boolean dealMachineStatus(GRecordMqttMessagePO messagePO) throws IOException {
        LocalDateTime now = LocalDateTime.now();
        GConfDevicePO devicePO = gConfDeviceDAO.findOne(GConfDevicePO::getSerialNumber, messagePO.getSerialNumber());
        GConfRoomDevicePO roomDevicePO = gConfRoomDeviceDAO.findOne(GConfRoomDevicePO::getDeviceId, devicePO.getId());
        GConfRoomPO roomPO = gConfRoomDAO.findById(roomDevicePO.getRoomId());
        // 将异常设备设置正常
        if (Objects.nonNull(devicePO.getRepairTime())
                && messagePO.getMessage().equals(DeviceErrorEnum.normal.getCode().toString())) {
            gConfDeviceDAO.updateDeviceRepair(devicePO.getId(), null);
            gRoomRepairRecordDAO.updateNormal(roomDevicePO.getRoomId());
            List<MRecordProductLookPO> lookPOS = mRecordProductLookDAO.findAllRepairByRoom(roomDevicePO.getRoomId());
            lookPOS.forEach(po -> {
                LocalDateTime endTime = now.plusMinutes(po.getRemainTime());
                mRecordProductLookDAO.updateNormal(po.getId(), endTime);
            });
            List<MRecordOccupyPO> occupyPOS = mRecordOccupyDAO.findAllRepairByRoom(roomDevicePO.getRoomId());
            occupyPOS.forEach(po -> {
                LocalDateTime endTime = now.plusMinutes(po.getRemainTime());
                mRecordOccupyDAO.updateNormal(po.getId(), endTime);
            });
        }
        // 将正常机器设置异常
        if (Objects.isNull(devicePO.getRepairTime())
                && !messagePO.getMessage().equals(DeviceErrorEnum.normal.getCode().toString())) {
            gConfDeviceDAO.updateDeviceRepair(devicePO.getId(), now);
            GRoomRepairRecordPO repairRecordPO = new GRoomRepairRecordPO();
            repairRecordPO.setRoomId(roomDevicePO.getRoomId());
            repairRecordPO.setRoomName(roomPO.getRoomName());
            repairRecordPO.setRoomType(roomPO.getRoomType());
            repairRecordPO.setDeviceId(devicePO.getId());
            repairRecordPO.setErrorCode(Integer.parseInt(messagePO.getMessage()));
            repairRecordPO.setErrorMessage(Objects.nonNull(DeviceErrorEnum.getByCode(repairRecordPO.getErrorCode())) ? DeviceErrorEnum.getByCode(repairRecordPO.getErrorCode()).getDesc() : "");
            repairRecordPO.setStatus(RepairStatusEnum.repairing.getCode());
            gRoomRepairRecordDAO.save(repairRecordPO);
            List<MRecordProductLookPO> lookPOS = mRecordProductLookDAO.findAllNormalNoEndByRoom(roomDevicePO.getRoomId());
            lookPOS.forEach(po -> {
                long minutesBetween = ChronoUnit.MINUTES.between(po.getEndTime(), now);
                mRecordProductLookDAO.updateRepair(po.getId(), (int) minutesBetween);
            });
            List<MRecordOccupyPO> occupyPOS = mRecordOccupyDAO.findAllNormalNoEndByRoom(roomDevicePO.getRoomId());
            occupyPOS.forEach(po -> {
                long minutesBetween = ChronoUnit.MINUTES.between(po.getEndTime(), now);
                mRecordOccupyDAO.updateRepair(po.getId(), (int) minutesBetween);
            });
            BackedMessage backedMessage = new BackedMessage();
            backedMessage.setId(roomPO.getId());
            backedMessage.setTitle(roomPO.getRoomName());
            backedMessage.setStatus("待维修");
            backedMessage.setMsgTime(LocalDateTimeUtil.format(LocalDateTime.now(), "yyyy-MM-dd HH:mm:ss"));
            messageProducer.sendMessage(MQTTTopicConstant.REPORT_REPAIR, JSON.toJSONString(backedMessage));
        }
        messagePO.setStatus(Boolean.TRUE);
        gRecordMqttMessageDAO.updateById(messagePO);
        return Boolean.TRUE;
    }

    @Override
    @Transactional
    public Boolean dealMachineSettle(GRecordMqttMessagePO messagePO) {
        LocalDate now = LocalDate.now();
        String message = messagePO.getMessage();
        String substring = message.substring(8);
        String hex = substring.substring(0, substring.length() - 4);
        int count = Integer.parseInt(hex, 16);
        Long score = new BigDecimal(1000).multiply(new BigDecimal(count)).longValue();
        GRecordGamePO gamePO = gRecordGameDAO.findByIdLock(messagePO.getGameId());
        GConfRoomPO roomPO = gConfRoomDAO.findById(gamePO.getRoomId());
        if (roomPO.getRoomType().equals(RoomTypeEnum.push_coins.getCode())) {
            log.error("设备类型配置出错");
            return Boolean.FALSE;
        }
        int pinecone = new BigDecimal(roomPO.getMultipleValue()).multiply(new BigDecimal(count)).intValue();
        Integer pineNut = Math.multiplyExact(pinecone, 10);
        gRecordGameDAO.updateData(gamePO.getId(), 0, pineNut, null);
        UAppUserEquityPO equityPO = uAppUserEquityDAO.findOne(UAppUserEquityPO::getUserId, gamePO.getUserId());
        UAppUserPO userPO = uAppUserDAO.findById(gamePO.getUserId());
        if (Objects.nonNull(gamePO.getRecordOccupyId())) {
            MConfVipPO vipPO = mConfVipDAO.findOne(MConfVipPO::getVipLevel, equityPO.getVipGrade());
            Integer getPinecone = new BigDecimal(pineNut).divide(new BigDecimal(vipPO.getExchangeRate()), 0, BigDecimal.ROUND_UP).intValue();
            mRecordOccupyDAO.settle(gamePO.getRecordOccupyId(), getPinecone);
            MRecordOccupyPO occupyPO = mRecordOccupyDAO.findById(gamePO.getRecordOccupyId());
            DDetailsPineconePO myDetail = new DDetailsPineconePO();
            myDetail.setUserId(gamePO.getUserId());
            myDetail.setLabelType(LabelTypeEnum.occupy.getCode());
            myDetail.setDetailsType(DetailsTypeEnum.income.getCode());
            myDetail.setPinecone(occupyPO.getPinecone() >= occupyPO.getCurrentPinecone() ? occupyPO.getPinecone() : occupyPO.getCurrentPinecone());
            myDetail.setRemark("包机记录ID:" + gamePO.getRecordOccupyId());
            dDetailsPineconeDAO.save(myDetail);
            uAppUserEquityDAO.addPinecone(gamePO.getUserId(), myDetail.getPinecone());
        } else {
            uAppUserEquityDAO.updatePineNut(gamePO.getUserId(), pineNut);
            DDetailsPineNutPO pineNutPO = new DDetailsPineNutPO();
            pineNutPO.setUserId(gamePO.getUserId());
            pineNutPO.setLabelType(PineNutLabelTypeEnum.game.getCode());
            pineNutPO.setDetailsType(DetailsTypeEnum.income.getCode());
            pineNutPO.setPineNut(pineNut);
            pineNutPO.setRoomId(roomPO.getId());
            pineNutPO.setRoomName(roomPO.getRoomName());
            dDetailsPineNutDAO.save(pineNutPO);
        }

        // 处理排行榜
        LocalDate monday = now.with(DayOfWeek.MONDAY);
        LocalDate sunday = now.with(DayOfWeek.SUNDAY);
        MRankArcadeMachinePO userRank = mRankArcadeMachineDAO.findUserRank(monday, sunday, roomPO.getMultipleType(), gamePO.getUserId());
        if (Objects.isNull(userRank)) {
            userRank = new MRankArcadeMachinePO();
            userRank.setUserId(gamePO.getUserId());
            userRank.setNickname(userPO.getNickname());
            userRank.setAvatarurl(userPO.getAvatarurl());
            userRank.setVipGrade(equityPO.getVipGrade());
            userRank.setRoomName(roomPO.getRoomName());
            userRank.setRankType(roomPO.getMultipleType());
            userRank.setHighestPoints(score.intValue());
            userRank.setIsRank(Boolean.FALSE);
            userRank.setStartDate(monday);
            userRank.setEndDate(sunday);
            userRank.setRecordTime(LocalDateTime.now());
            mRankArcadeMachineDAO.save(userRank);
        } else if (userRank.getHighestPoints() < score) {
            userRank.setNickname(userPO.getNickname());
            userRank.setAvatarurl(userPO.getAvatarurl());
            userRank.setVipGrade(equityPO.getVipGrade());
            userRank.setRoomName(roomPO.getRoomName());
            userRank.setHighestPoints(score.intValue());
            userRank.setRecordTime(LocalDateTime.now());
            mRankArcadeMachineDAO.updateById(userRank);
        }

        // 校验挑战任务
        if (roomPO.getRoomType().equals(RoomTypeEnum.arcade_machine.getCode())) {
            MRecordBattleArcadeMachinePO machinePO = mRecordBattleArcadeMachineDAO.findLatestBattleByUserId(gamePO.getUserId());
            if (Objects.nonNull(machinePO) && machinePO.getStatus().equals(BattleStatusEnum.battling.getCode())) {
                if (machinePO.getPineNut() < pineNut) {
                    machinePO.setGameId(gamePO.getId());
                    machinePO.setPineNut(pineNut);
                    MRankBattleArcadeMachinePO po = mRankBattleArcadeMachineDAO.findById(machinePO.getBattleId());
                    if (po.getPineNut() <= pineNut) {
                        machinePO.setStatus(BattleStatusEnum.unclaimed.getCode());
                    }
                    mRecordBattleArcadeMachineDAO.updateById(machinePO);
                }
            }
        } else {
            MRecordBattleRecreationPO recreationPO = mRecordBattleRecreationDAO.findLatestBattleByUserId(gamePO.getUserId());
            if (Objects.nonNull(recreationPO) && recreationPO.getStatus().equals(BattleStatusEnum.battling.getCode())) {
                if (recreationPO.getPineNut() < pineNut) {
                    recreationPO.setGameId(gamePO.getId());
                    recreationPO.setPineNut(pineNut);
                    MRankBattleRecreationPO po = mRankBattleRecreationDAO.findById(recreationPO.getBattleId());
                    if (po.getPineNut() <= pineNut) {
                        recreationPO.setStatus(BattleStatusEnum.unclaimed.getCode());
                    }
                    mRecordBattleRecreationDAO.updateById(recreationPO);
                }
            }
        }
        boolean flag = Boolean.FALSE;
        int prizePinecone = 0;
        // 处理暴击奖
        GConfPrizePO confPrizePO = gConfPrizeDAO.findOneMachinePrize(PrizeTypeEnum.critical_strike.getCode(), roomPO.getMultipleType());
        if (Objects.nonNull(confPrizePO)) {
            List<GConfPrizeItemPO> itemPOS = gConfPrizeItemDAO.findList(GConfPrizeItemPO::getPrizeId, confPrizePO.getId(), GConfPrizeItemPO::getScore);
            for (GConfPrizeItemPO po : itemPOS) {
                if (po.getScore() <= score) {
                    DDetailsPineconePO myDetail = new DDetailsPineconePO();
                    myDetail.setUserId(gamePO.getUserId());
                    myDetail.setLabelType(LabelTypeEnum.reward.getCode());
                    myDetail.setDetailsType(DetailsTypeEnum.income.getCode());
                    prizePinecone = Math.multiplyExact(po.getItemValue(), roomPO.getMultipleValue());
                    myDetail.setPinecone(prizePinecone);
                    myDetail.setRemark("暴击奖" + score);
                    dDetailsPineconeDAO.save(myDetail);
                    uAppUserEquityDAO.addPinecone(gamePO.getUserId(), prizePinecone);
                    // 新增赏金审批记录
                    GRecordPrizePO prizePO = new GRecordPrizePO();
                    prizePO.setUserId(gamePO.getUserId());
                    prizePO.setRoomId(roomPO.getId());
                    prizePO.setRoomName(roomPO.getRoomName());
                    prizePO.setRoomType(roomPO.getRoomType());
                    prizePO.setPrizeScore(score);
                    prizePO.setPrizeType("暴击" + score);
                    prizePO.setPrizePinecone(prizePinecone);
                    prizePO.setStatus(PrizeStatusEnum.issued.getCode());
                    gRecordPrizeDAO.save(prizePO);
                    flag = Boolean.TRUE;
                    break;
                }
            }
        }
        if (flag) {
            // 每日任务累计赏金
            String dailyKey = gamePO.getUserId() + now.toString() + "dailyTask";
            String key = gamePO.getUserId() + now.toString() + "task";
            baseUtilService.setDailyTask(dailyKey, gamePO.getUserId(), now);
            baseUtilService.setTask(key, gamePO.getUserId());
            List<MRecordTaskDailyPO> list = mRecordTaskDailyDAO.findUserTodayAction(gamePO.getUserId(), now, DailyTaskActionEnum.total_prize.getCode());
            if (CollectionUtils.isNotEmpty(list)) {
                list.forEach(po -> {
                    po.setCurrentProgress(Math.addExact(po.getCurrentProgress(), 1));
                    if (po.getCurrentProgress() >= po.getThreshold() && po.getStatus().equals(TaskStatusEnum.go_complete.getCode())) {
                        po.setStatus(TaskStatusEnum.unclaimed.getCode());
                    }
                });
                mRecordTaskDailyDAO.updateBatchById(list);
            }
            baseUtilService.dealDailyTaskAllComplete(gamePO.getUserId(), now);
            // 长期任务累计赏金
            List<MRecordTaskPO> pos = mRecordTaskDAO.findList(gamePO.getUserId(), TaskActionEnum.total_prize.getCode(), Collections.singletonList(TaskStatusEnum.go_complete.getCode()));
            if (CollectionUtils.isNotEmpty(pos)) {
                pos.forEach(po -> {
                    po.setCurrentProgress(Math.addExact(po.getCurrentProgress(), 1));
                    if (po.getCurrentProgress() >= po.getThreshold()) {
                        po.setStatus(TaskStatusEnum.unclaimed.getCode());
                    }
                });
                mRecordTaskDAO.updateBatchById(pos);
            }

            // 长期任务累计暴击奖
            List<MRecordTaskPO> jpPos = mRecordTaskDAO.findList(gamePO.getUserId(), TaskActionEnum.total_critical_hit.getCode(), Collections.singletonList(TaskStatusEnum.go_complete.getCode()));
            if (CollectionUtils.isNotEmpty(jpPos)) {
                jpPos.forEach(po -> {
                    po.setCurrentProgress(Math.addExact(po.getCurrentProgress(), 1));
                    if (po.getCurrentProgress() >= po.getThreshold()) {
                        po.setStatus(TaskStatusEnum.unclaimed.getCode());
                    }
                });
                mRecordTaskDAO.updateBatchById(jpPos);
            }

            // 新增公告
            MRecordNoticePO noticePO = new MRecordNoticePO();
            noticePO.setNoticeType(NoticeTypeEnum.CRITICAL.getCode());
            noticePO.setPinecone(prizePinecone);
            noticePO.setUserId(gamePO.getUserId());
            noticePO.setRoomId(roomPO.getId());
            noticePO.setRoomName(roomPO.getRoomName());
            mRecordNoticeDAO.save(noticePO);

            // 推送弹幕
            BarrageMessage barrageMessage = new BarrageMessage();
            barrageMessage.setRoomId(roomPO.getId());
            barrageMessage.setNickName(userPO.getNickname());
            barrageMessage.setAvatarurl(userPO.getAvatarurl());
            barrageMessage.setVipLevel(equityPO.getVipGrade());
            barrageMessage.setContent("打出暴击，奖励" + prizePinecone + "松果");
        }
        gRecordGameDAO.updateGameEnd(gamePO.getId());
        messagePO.setStatus(Boolean.TRUE);
        gRecordMqttMessageDAO.updateById(messagePO);
        return Boolean.TRUE;
    }
}
